#include "CCamera.h"
#include "videodecode.h" // 虽然不直接持有，但 ReadThread 可能需要
#include <QMediaDevices>
#include <QDebug>

// FFmpeg 头文件，ReadThread 可能需要，或者在这里包含以确保 AVFrame 定义完整
extern "C" {
#include "libavutil/frame.h"
}

CCamera::CCamera(QObject *parent)
    : QObject(parent), isCapturing_(false)
{
    // 创建读取线程，传递 this 作为父对象
    readThread_ = new ReadThread(this);

    // 连接 ReadThread 的信号到 CCamera 的内部槽函数
    // 注意：ReadThread::repaint 发出的是克隆帧，需要 QueuedConnection
    connect(readThread_, &ReadThread::repaint, this, &CCamera::onFrameReceived, Qt::QueuedConnection);
    connect(readThread_, &ReadThread::playState, this, &CCamera::onThreadStateChanged);

    // 立即发现摄像头
    discoverCameras();
}

CCamera::~CCamera()
{
    // 确保线程在析构前停止
    stopCapture();
    // readThread_ 会被 Qt 自动删除，因为它设置了父对象
}

void CCamera::discoverCameras()
{
    availableCameras_ = QMediaDevices::videoInputs();
    cameraDescriptions_.clear();
    for (const QCameraDevice &device : availableCameras_) {
        cameraDescriptions_.append(device.description());
    }

    qInfo() << "发现摄像头设备:" << cameraDescriptions_;
    emit cameraListUpdated(cameraDescriptions_); // 发出信号通知 UI 更新

    // 尝试选择默认摄像头
    if (!availableCameras_.isEmpty()) {
        QCameraDevice defaultCamera = QMediaDevices::defaultVideoInput();
        int defaultIndex = -1;
        for (int i = 0; i < availableCameras_.size(); ++i) {
            if (availableCameras_[i] == defaultCamera) {
                defaultIndex = i;
                break;
            }
        }
        if (defaultIndex != -1) {
            selectCamera(defaultIndex);
        } else {
            selectCamera(0); // 默认选择第一个
        }
    } else {
        selectedCamera_ = QCameraDevice(); // 重置选中的摄像头
        qWarning() << "未找到可用摄像头设备。";
        emit errorOccurred("未找到可用摄像头设备。");
    }
}

QStringList CCamera::getAvailableCamerasDescriptions() const
{
    return cameraDescriptions_;
}

bool CCamera::selectCamera(int index)
{
    if (index >= 0 && index < availableCameras_.size()) {
        if (selectedCamera_ != availableCameras_[index]) {
             selectedCamera_ = availableCameras_[index];
             qInfo() << "已选择摄像头:" << getSelectedCameraDescription();
             // 如果正在捕获中切换摄像头，需要先停止再启动 (这里简化为仅选择)
             if (isCapturing_) {
                 qWarning() << "切换摄像头需要先停止当前捕获。";
                 // stopCapture(); // 或者根据需要自动重启
             }
        }
        return true;
    } else {
        qWarning() << "选择摄像头索引无效:" << index;
        return false;
    }
}

QString CCamera::getSelectedCameraDescription() const
{
    return selectedCamera_.description();
}

QString CCamera::getSelectedCameraNameForFFmpeg() const
{
    if (selectedCamera_.isNull()) {
        return QString();
    }
    // 根据操作系统和 FFmpeg dshow/v4l2/avfoundation 的要求格式化名称
#if defined(Q_OS_WIN)
    return QString("video=%1").arg(selectedCamera_.description());
#elif defined(Q_OS_LINUX)
    // Linux 可能直接用 /dev/videoX，这需要更复杂的映射
    // QCameraDevice::id() 返回的可能是设备路径，可以尝试使用
    // return selectedCamera_.id(); // 不确定是否总是有效
    // 或者仍然尝试描述？
     return selectedCamera_.description(); // 尝试描述，不确定效果
     // 最好的方法可能是提供配置或更智能的探测
#elif defined(Q_OS_MAC)
    // AVFoundation 可能使用 index 或 unique ID
    // return QString::number(availableCameras_.indexOf(selectedCamera_)); // 尝试用索引
     return selectedCamera_.id(); // 尝试用 ID
#else
    return selectedCamera_.description(); // 默认回退
#endif
}


bool CCamera::startCapture()
{
    if (isCapturing_) {
        qDebug() << "摄像头已经在捕获中。";
        return true;
    }
    if (selectedCamera_.isNull()) {
        emit errorOccurred("未选择有效的摄像头设备。");
        return false;
    }
    if (readThread_->isRunning()) {
         qWarning() << "读取线程已经在运行，无法重复启动。";
         // 可能需要先确保线程完全停止
         stopCapture(); // 尝试先停止
    }

    QString deviceName = getSelectedCameraNameForFFmpeg();
    if (deviceName.isEmpty()) {
        emit errorOccurred("无法获取用于 FFmpeg 的摄像头名称。");
        return false;
    }

    qInfo() << "开始捕获摄像头:" << deviceName;
    readThread_->open(deviceName); // open 会启动线程

    // 注意：线程状态可能不会立即改变，isCapturing_ 的更新最好放在 onThreadStateChanged 中
    // isCapturing_ = true; // 暂时在这里设置，后面会由状态信号更新
    // emit captureStateChanged(true);

    return true;
}

void CCamera::stopCapture()
{
    if (!isCapturing_ && !readThread_->isRunning()) {
        //qDebug() << "摄像头未在捕获中。";
        return;
    }

    qInfo() << "请求停止摄像头捕获...";
    readThread_->close(); // 请求线程停止读取循环

    // 等待线程结束
    if (readThread_->isRunning()) {
        if (!readThread_->wait(3000)) { // 等待最多 3 秒
            qWarning() << "等待摄像头读取线程结束超时，可能需要强制终止。";
            readThread_->terminate(); // 强制终止（非推荐）
            readThread_->wait();      // 再次等待
        } else {
             qDebug() << "摄像头读取线程已停止。";
        }
    }

    // isCapturing_ 的状态由 onThreadStateChanged(end) 更新
}

bool CCamera::isCapturing() const
{
    // 返回基于状态变量的值，该变量由线程状态信号更新
    return isCapturing_;
    // 或者直接查询线程状态，但不那么精确，因为状态可能是中间态
    // return readThread_ && readThread_->isRunning();
}

// --- 私有槽函数 ---

void CCamera::onFrameReceived(AVFrame* frame)
{
    // 直接将收到的克隆帧转发出去
    emit frameReady(frame);
}

void CCamera::onThreadStateChanged(ReadThread::PlayState state)
{
    bool newState = (state == ReadThread::play);
    if (newState != isCapturing_) {
        isCapturing_ = newState;
        qInfo() << "摄像头捕获状态改变为:" << (isCapturing_ ? "运行中" : "已停止");
        emit captureStateChanged(isCapturing_);

        // 如果状态变为停止 (end)，可以检查是否有错误导致
        if (!isCapturing_) {
             // ReadThread 没有提供错误信息，可以在 VideoDecode 中添加信号
             // 或者在 CCamera 中检查 ReadThread 的退出码等（如果 ReadThread 支持）
        }
    }
}
